import time
#作用域概念
'''
作用域：程序创建，访问，改变一个变量时，都是在同一个保存变量的空间内进行，称为命名空间，也叫作用域
内置变量：built-in，在python环境中，任意模块，任意位置都可以被访问，调用
全局变量：global，只能被当前模块访问，调用，使用global关键字可以将局部变量变成全局变量
自由变量：Enclosed（嵌套），在嵌套函数中，访问函数体之外的非全局变量，大量运用于闭包
局部变量：local，只作用于当前函数体---一旦在函数体中进行赋值操作，该变量相对该函数来说就是局部变量---
'''
#作用域之间的转换
a=0
def f_1():
    #将局部变量a转换为全局变量a
    global a
f_1()

def f_2():
    b=0
    c=0
    def f_2_1(d):
        #将局部变量b，c转化为自由变量
        nonlocal b,c
        b+=d
        c+=1
        return b/c
    return f_2_1
res_2=f_2()
print(res_2(5))

#闭包：延伸了作用域的函数，对应作用域中自由变量Enclosed的概念

#装饰器：
# 实现原理：闭包
# 本质是：延伸了被装饰函数的作用域，将函数作为参数传给可调用对象-函数或类
# 目的是：增加或扩展可调用对象的行为


#如果不使用装饰器
'''
def foo_3(a,b,c):
    count=1
    while True:
        if count>a**b*c:
            break
        count+=1
    return f'foo_3函数运行结果：{a**b*c}'

def foo_4(func,*args,**kwargs):
    start=time.time()
    res=foo_3(*args,**kwargs)
    end=time.time()
    print(f"{func.__name__}函数运行耗时为：{format(end-start,'.2f')}s")
    return res

res=foo_4(foo_3,10,5,55)
print(res)
'''

def foo_4_deco(func):
    def wrapper(*args,**kwargs):
        start=time.time()
        res=func(*args,**kwargs)
        end=time.time()
        print(f"{func.__name__}函数运行耗时为：{format(end-start,'.2f')}s")
        return res
    return wrapper

#通过@关键字实现装饰器
#当不想打印时，将@foo_4_deco注释掉
@foo_4_deco
def foo_3(a,b,c):
    count=1
    while True:
        if count>a**b*c:
            break
        count+=1

foo_3(10,2,3)

#使用装饰器为裴波那契函数添加缓存
def pb_deco(func):
    a={}
    def wrapper(n):
        if n in a.values():
            return a[n]
        else:
            print('没有缓存',n)
            res=func(n)
            a[n]=res
            return res
    return wrapper

@pb_deco
def pb(n):
    if n<=1 and n>=0:
        return n
    else:
        return pb(n-1)+pb(n-2)

print(pb(8))